using System;
using System.Collections;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using YooAssetsSystem.Patch;
using TMPro;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.U2D;
using UnityEngine.UI;
using YooAsset;

namespace YooAssetsSystem.Samples
{
    /// <summary>
    /// YooAssets 样例
    /// </summary>
    public partial class YooAsstsSample : MonoBehaviour
    {
        /// <summary>
        /// 资源服务
        /// </summary>
        private YAService_Entity yooAssetService;

        /// <summary>
        /// 下载模式
        /// </summary>
        public EPlayMode ePlayMode;
    }

    public partial class YooAsstsSample
    {

        #region 初始化

        public void Start()
        {
            DontDestroyOnLoad(this);
            if (yooAssetService == null)
                yooAssetService = new YAService_Entity();
            SetDownLoadAddPkgBtn(false);
            SetDefaultPkgBtnItem(false);
            SetAddPkgBtnItemParent(false);
        }

        #endregion

        #region 非关键样例 代码段

        protected void SetDownLoadAddPkgBtn(bool isEnable)
        {
            GameObject.Find("Root/Canvas/DownLoad_AddPkg").GetComponent<Button>().interactable = isEnable;
        }

        protected void SetDefaultPkgBtnItem(bool isEnable)
        {
            GameObject.Find("Root/Canvas/To DefualtPkg Scene").GetComponent<Button>().interactable = isEnable;
        }

        protected void SetAddPkgBtnItemParent(bool isEnable)
        {
            GameObject.Find("Root/Canvas/AddPkg").SetActive(isEnable);
        }

        /// <summary>
        protected void Log(string type, string async, string pkg, string assetName)
        {
            Debug.Log($"资源加载 成功 -- type: {type} - async: {async} - pkg: {pkg} - assetName: {assetName}");
        }

        #endregion

        #region 下载 热更包

        /// <summary>
        /// 下载 默认主包
        /// </summary>
        public void Test_YooAssetPkgDownload_DefaultPacakge()
        {
            EPlayMode playMode = ePlayMode;
            string url = "https://zongyi-cdn-src.oss-cn-beijing.aliyuncs.com/ddz-app/wx/YooassetTest/TestYooAssetSystem";
            string appVersion = "1";
            string packageName = "DefaultPackage";
            bool isDefaultPackage = true;
            string[] loadTags = new string[0];
            bool isCustomizeUrl = false;

            YAService_Entity.Instance.DownloadPackage(playMode, url, appVersion, packageName, isDefaultPackage, loadTags, isCustomizeUrl, Event_ChangeStateEvent, Event_PatchDoneEvent_DefaultPackage, Event_UpdateFailedEvent, Event_NeedDownloadEvent).Forget();
        }

        /// <summary>
        /// 下载 分包
        /// </summary>
        public void Test_YooAssetPkgDownload_AddPkg()
        {
            EPlayMode playMode = ePlayMode;
            string url = "https://zongyi-cdn-src.oss-cn-beijing.aliyuncs.com/ddz-app/wx/YooassetTest/TestYooAssetSystem";
            string appVersion = "1";
            string packageName = "AddPkg";
            bool isDefaultPackage = false;
            string[] loadTags = new string[0];
            bool isCustomizeUrl = false;

            YAService_Entity.Instance.DownloadPackage(playMode, url, appVersion, packageName, isDefaultPackage, loadTags, isCustomizeUrl, Event_ChangeStateEvent, Event_PatchDoneEvent_AddPkg, Event_UpdateFailedEvent, Event_NeedDownloadEvent).Forget();
        }

        /// <summary>
        /// 回调事件 下载 流程 状态切换
        /// </summary>
        /// <param name="msg"></param>
        private void Event_ChangeStateEvent(string msg)
        {
            Debug.Log($"{GetType().FullName}:: ChangeStateEvent: {msg}");
        }

        /// <summary>
        /// 回调事件 下载 结束 默认包的处理
        /// </summary>
        /// <param name="msg"></param>
        private void Event_PatchDoneEvent_DefaultPackage(string msg)
        {
            Debug.Log($"{GetType().FullName}:: PatchDoneEvent: {msg}");
            Test_YooAssetPkgLoad().Forget();
            SetDefaultPkgBtnItem(true);
            SetDownLoadAddPkgBtn(true);
        }

        /// <summary>
        /// 回调事件 下载 结束 分包的处理
        /// </summary>
        /// <param name="msg"></param>
        private void Event_PatchDoneEvent_AddPkg(string msg)
        {
            Debug.Log($"{GetType().FullName}:: PatchDoneEvent: {msg}");
            SetAddPkgBtnItemParent(true);
        }

        /// <summary>
        /// 回调事件 下载 失败
        /// </summary>
        /// <param name="msg"></param>
        private void Event_UpdateFailedEvent(string msg)
        {
            Debug.Log($"{GetType().FullName}:: UpdateFailedEvent: {msg}");
        }

        /// <summary>
        /// 回调事件 下载 需要下载的情况
        /// 里面有个UnityAction，可以给UI来使用
        /// 例如： 给用户提示有多少内容需要下载，点击开始才进行下载
        /// </summary>
        /// <param name="fileNum">总文件数量</param>
        /// <param name="totalSize">总大小</param>
        /// <param name="toDownload">开始下载的事件</param>
        private void Event_NeedDownloadEvent(int fileNum, long totalSize, UnityAction toDownload)
        {
            Debug.Log($"{GetType().FullName}:: Event_NeedDownloadEvent 文件数: {fileNum} -- 总大小: {totalSize}");
            toDownload?.Invoke();
        }

        /// <summary>
        /// 无参代码参考性，用来表示默认包已经下载完了，加载里面的一个资源
        /// </summary>
        private async UniTaskVoid Test_YooAssetPkgLoad()
        {
            GameObject objPre = await YAService_Entity.Instance.LoadPrefab_Async("Cube");
            AsyncInstantiateOperation opoeration = InstantiateAsync(objPre);
            await opoeration.ToUniTask();

            GameObject obj = (GameObject)opoeration.Result[0];
            obj.transform.position = new Vector3(-1f, 1f, 0f);
            obj.transform.rotation = new Quaternion(-45f, -12f, 0, 0);

            Debug.Log($"{GetType().FullName}:: Test_YooAssetPkgLoad -- obj: {obj.name}");
        }

        #endregion

        #region 功能函数

        /// <summary>
        /// 测试 默认包 资源是否存在
        /// </summary>
        /// <returns></returns>
        public void Test_DefaultPkg_CheckLocationValid()
        {
            UniTask.ToCoroutine(async () =>
            {
                //资源存在
                bool check_1 = YAService_Entity.Instance.CheckLocationValid("Cube");
                Assert.IsTrue(check_1);
                Debug.Log($"资源是否存在 默认包 Cube check_1:{check_1}");

                //资源不存在
                bool check_2 = YAService_Entity.Instance.CheckLocationValid("Cube1");
                Assert.IsTrue(!check_2);
                Debug.Log($"资源是否存在 默认包 Cube1 check_2:{check_2}");
            });
        }

        /// <summary>
        /// 测试 扩展包 资源是否存在
        /// </summary>
        public void Test_AddPkg_CheckLocationValid()
        {
            UniTask.ToCoroutine(async () =>
            {
                //资源存在
                bool check_1 = YAService_Entity.Instance.CheckLocationValid("demo_prefab", "AddPkg");
                Assert.IsTrue(check_1);
                Debug.Log($"资源是否存在 扩展包 demo_prefab check_1:{check_1}");

                //资源不存在
                bool check_2 = YAService_Entity.Instance.CheckLocationValid("demo_prefab1", "AddPkg");
                Assert.IsTrue(!check_2);
                Debug.Log($"资源是否存在 扩展包 demo_prefab1 check_2:{check_2}");
            });
        }

        #endregion

        #region 加载 场景

        /// <summary>
        /// 切换到 默认包 中的 独立 场景
        /// </summary>
        public void Test_Load_DefaultPkg_Scene_Single()
        {
            UniTask.ToCoroutine(async () =>
            {
                string sceneName = "Demo";
                string pkgName = "DefaultPackage";

                try
                {
                    await YAService_Entity.Instance.LoadScene_Async(sceneName, LoadSceneMode.Single, (process) =>
                    {
                        Debug.Log($"Test_Load_DefaultPkg_Scene_Single sceneName: {sceneName} 场景加载进度: {process}");
                    }, pkgName, (scene) =>
                    {
                        Debug.Log($"Test_Load_DefaultPkg_Scene_Single sceneName: {sceneName} 场景加载完成: {scene.name}");
                    });
                }
                catch (Exception ex)
                {
                    Debug.LogError($"Test_Load_DefaultPkg_Scene_Single sceneName: {sceneName} 场景加载失败 -- ex: {ex.Message}");
                }
            });
        }

        /// <summary>
        /// 切换到 插件包 中的 独立 场景
        /// </summary>
        public void Test_Load_AddScene_Scene_Single()
        {
            UniTask.ToCoroutine(async () =>
            {
                string sceneName = "addonDemo";
                string pkgName = "AddPkg";

                try
                {
                    await YAService_Entity.Instance.LoadScene_Async(sceneName, LoadSceneMode.Single, (process) =>
                    {
                        Debug.Log($"Test_Load_AddScene_Scene_Single sceneName: {sceneName} 场景加载进度: {process}");
                    }, pkgName, (scene) =>
                    {
                        Debug.Log($"Test_Load_AddScene_Scene_Single sceneName: {sceneName} 场景加载完成: {scene.name}");
                    });
                }
                catch (Exception ex)
                {
                    Debug.LogError($"Test_Load_AddScene_Scene_Single sceneName: {sceneName} 场景加载失败 -- ex: {ex.Message}");
                }
            });
        }

        /// <summary>
        /// 加载 插件包 中的 附加 场景
        /// </summary>
        public void Test_Load_AddScene_Scene_Additive()
        {
            UniTask.ToCoroutine(async () =>
            {
                string sceneName = "addonDemoAdditive";
                string pkgName = "AddPkg";

                try
                {
                    await YAService_Entity.Instance.LoadScene_Async(sceneName, LoadSceneMode.Additive, (process) =>
                    {
                        Debug.Log($"Test_Load_AddScene_Scene_Additive sceneName: {sceneName} 场景加载进度: {process}");
                    }, pkgName, (scene) =>
                    {
                        Debug.Log($"Test_Load_AddScene_Scene_Additive sceneName: {sceneName} 场景加载完成: {scene.name}");
                    });
                }
                catch (Exception ex)
                {
                    Debug.LogError($"Test_Load_AddScene_Scene_Additive sceneName: {sceneName} 场景加载失败 -- ex: {ex.Message}");
                }
            });
        }

        /// <summary>
        /// 卸载 插件包 中的 附加 场景
        /// </summary>
        public void Test_UnLoad_AddScene_Scene_Additive()
        {
            UniTask.ToCoroutine(async () =>
            {
                string sceneName = "addonDemoAdditive";
                string pkgName = "AddPkg";

                try
                {
                    await YAService_Entity.Instance.UnLoadScene_Async(sceneName, pkgName);
                }
                catch (Exception ex)
                {
                    Debug.LogError($"Test_UnLoad_AddScene_Scene_Additive sceneName: {sceneName} 场景卸载失败 -- ex: {ex.Message}");
                }
            });
        }

        #endregion

        #region 加载 各种资源

        /*
         * 从扩展包中加载资源
         *
         * 0、Prefab
         * 1、GameObject
         * 2、TextAsset
         * 3、Sprite
         * 4、Texture2d
         * 5、AudioClip
         * 6、AnimationClip
         * 7、ScriptableObject
         * 8、material
         * 9、Shader
         * 11、dll
         * 12、TextMeshPro
         * 
        */

        /// <summary>
        /// 加载 扩展包 预制(Prefab)
        /// </summary>
        public void Test_Load_AddPkg_Prefab()
        {
            UniTask.ToCoroutine(async () =>
            {
                GameObject prefab_Sync = YAService_Entity.Instance.LoadPrefab_Sync("demo_prefab", "AddPkg");
                GameObject obj_Sync = Instantiate(prefab_Sync);
                Assert.IsNotNull(obj_Sync);
                Log("Prefab", "Sync", "AddPkg", "demo_prefab");

                GameObject prefab_Async = await YAService_Entity.Instance.LoadPrefab_Async("demo_prefab", "AddPkg");
                AsyncInstantiateOperation opoeration = InstantiateAsync(prefab_Async);
                await opoeration.ToUniTask();
                Assert.IsNotNull(opoeration.Result);
                Log("Prefab", "Async", "AddPkg", "demo_prefab");
            });
        }

        /// <summary>
        /// 加载 扩展包 对象(GameObject)
        /// </summary>
        public void Test_Load_AddPkg_GameObject()
        {
            UniTask.ToCoroutine(async () =>
            {
                GameObject prefab_Sync = YAService_Entity.Instance.LoadGameObject_Sync("demo_gameobj", true, null, "AddPkg");
                GameObject obj_Sync = Instantiate(prefab_Sync);
                Assert.IsNotNull(obj_Sync);
                Log("GameObject", "Sync", "AddPkg", "demo_gameobj");

                GameObject prefab_Async = await YAService_Entity.Instance.LoadGameObject_Async("demo_gameobj", true, null, "AddPkg");
                AsyncInstantiateOperation opoeration = InstantiateAsync(prefab_Async);
                await opoeration.ToUniTask();
                Assert.IsNotNull(opoeration.Result);
                Log("GameObject", "Async", "AddPkg", "demo_gameobj");
            });
        }

        /// <summary>
        /// 加载 扩展包 文本(TextAsset)
        /// </summary>
        public void Test_Load_AddPkg_TextAsset()
        {
            UniTask.ToCoroutine(async () =>
            {
                TextAsset textAsset_Sync = YAService_Entity.Instance.LoadTextAsset_Sync("demo_textasset", "AddPkg");
                Assert.IsNotNull(textAsset_Sync.text);
                Log("TextAsset", "Sync", "AddPkg", "demo_textasset");

                TextAsset textAsset_Async = await YAService_Entity.Instance.LoadTextAsset_Async("demo_textasset", "AddPkg");
                Assert.IsNotNull(textAsset_Async.text);
                Log("TextAsset", "Async", "AddPkg", "demo_textasset");
            });
        }

        /// <summary>
        /// 加载 扩展包 Sprite
        /// </summary>
        public void Test_Load_AddPkg_Sprite()
        {
            UniTask.ToCoroutine(async () =>
            {
                List<Sprite> sprites_Sync = YAService_Entity.Instance.LoadSprites_Sync("demo_sprite", "AddPkg");
                Assert.IsTrue(sprites_Sync.Count > 0);
                Log("Sprite", "Sync", "AddPkg", "demo_sprite");

                List<Sprite> sprites_Async = await YAService_Entity.Instance.LoadSprites_Async("demo_sprite", "AddPkg");
                Assert.IsTrue(sprites_Async.Count > 0);
                Log("Sprite", "Async", "AddPkg", "demo_sprite");
            });
        }

        /// <summary>
        /// 加载 扩展包 图集
        /// </summary>
        public void Test_Load_AddPkg_SpriteAtlas()
        {
            UniTask.ToCoroutine(async () =>
            {
                SpriteAtlas spriteAtlas_Sync = YAService_Entity.Instance.LoadSpriteAtlas_Sync("demo_spriteatlas", "AddPkg");
                Assert.IsNotNull(spriteAtlas_Sync);
                Log("SpriteAtlas", "Sync", "AddPkg", "demo_spriteatlas");

                SpriteAtlas spriteAtlas_Async = await YAService_Entity.Instance.LoadSpriteAtlas_Async("demo_spriteatlas", "AddPkg");
                Assert.IsNotNull(spriteAtlas_Async);
                Log("SpriteAtlas", "Async", "AddPkg", "demo_spriteatlas");
            });
        }

        /// <summary>
        /// 加载 扩展包 音频(AudioClip)
        /// </summary>
        public void Test_Load_AddPkg_AudioClip()
        {
            UniTask.ToCoroutine(async () =>
            {
                AudioClip audioClip_Sync = YAService_Entity.Instance.LoadAudioClip_Sync("demo_audioclip", "AddPkg");
                Assert.IsNotNull(audioClip_Sync);
                Log("AudioClip", "Sync", "AddPkg", "demo_audioclip");

                AudioClip audioClip_Async = await YAService_Entity.Instance.LoadAudioClip_Async("demo_audioclip", "AddPkg");
                Assert.IsNotNull(audioClip_Async);
                Log("AudioClip", "Async", "AddPkg", "demo_audioclip");
            });
        }

        /// <summary>
        /// 加载 扩展包 动画(AnimationClip)
        /// </summary>
        public void Test_Load_AddPkg_AnimationClip()
        {
            UniTask.ToCoroutine(async () =>
            {
                AnimationClip animationClip_Sync =
                    YAService_Entity.Instance.LoadAnimationClip_Sync("demo_animationclip", "AddPkg");
                Assert.IsNotNull(animationClip_Sync);
                Log("AnimationClip", "Sync", "AddPkg", "demo_animationclip");

                AnimationClip animationClip_Async =
                    await YAService_Entity.Instance.LoadAnimationClip_Async("demo_animationclip", "AddPkg");
                Assert.IsNotNull(animationClip_Async);
                Log("AnimationClip", "Async", "AddPkg", "demo_animationclip");
            });
        }

        /// <summary>
        /// 加载 扩展包 脚本(ScriptableObject)
        /// </summary>
        public void Test_Load_AddPkg_ScriptableObject()
        {
            UniTask.ToCoroutine(async () =>
            {
                ScriptableObject animationClip_Sync =
                    YAService_Entity.Instance.LoadScriptableObject_Sync("demo_scriptable", "AddPkg");
                Assert.IsNotNull(animationClip_Sync);
                Log("ScriptableObject", "Sync", "AddPkg", "demo_scriptable");

                ScriptableObject animationClip_Async =
                    await YAService_Entity.Instance.LoadScriptableObject_Async("demo_scriptable", "AddPkg");
                Assert.IsNotNull(animationClip_Async);
                Log("ScriptableObject", "Async", "AddPkg", "demo_scriptable");
            });
        }

        /// <summary>
        /// 加载 扩展包 材质(Material)
        /// </summary>
        public void Test_Load_AddPkg_Material()
        {
            UniTask.ToCoroutine(async () =>
            {
                Material animationClip_Sync =
                    YAService_Entity.Instance.LoadMaterial_Sync("demo_material", "AddPkg");
                Assert.IsNotNull(animationClip_Sync);
                Log("Material", "Sync", "AddPkg", "demo_material");

                Material animationClip_Async =
                    await YAService_Entity.Instance.LoadMaterial_Async("demo_material", "AddPkg");
                Assert.IsNotNull(animationClip_Async);
                Log("Material", "Async", "AddPkg", "demo_material");
            });
        }

        /// <summary>
        /// 加载 扩展包 着色器(Shader)
        /// </summary>
        public void Test_Load_AddPkg_Shader()
        {
            UniTask.ToCoroutine(async () =>
            {
                Shader animationClip_Sync =
                    YAService_Entity.Instance.LoadShader_Sync("demo_shader", "AddPkg");
                Assert.IsNotNull(animationClip_Sync);
                Log("Shader", "Sync", "AddPkg", "demo_shader");

                Shader animationClip_Async =
                    await YAService_Entity.Instance.LoadShader_Async("demo_shader", "AddPkg");
                Assert.IsNotNull(animationClip_Async);
                Log("Shader", "Async", "AddPkg", "demo_shader");
            });
        }

        /// <summary>
        /// 加载 扩展包 dll(TextAsset)
        /// </summary>
        public void Test_Load_AddPkg_Dll()
        {
            UniTask.ToCoroutine(async () =>
            {
                TextAsset dll_Sync = YAService_Entity.Instance.LoadDll_Sync("demo_dll", "AddPkg");
                Assert.IsNotNull(dll_Sync.bytes);
                Log("Dll", "Sync", "AddPkg", "demo_dll");

                TextAsset dll_Async = await YAService_Entity.Instance.LoadDll_Async("demo_dll", "AddPkg");
                Assert.IsNotNull(dll_Async.bytes);
                Log("Dll", "Async", "AddPkg", "demo_dll");
            });
        }

        /// <summary>
        /// 加载 扩展包 文本(TextMeshPro)
        /// </summary>
        public void Text_Load_AddPkg_TextMeshPro()
        {
            UniTask.ToCoroutine(async () =>
            {
                TMP_FontAsset textAsset_Sync = YAService_Entity.Instance.LoadTMPFont_Sync("demo_textmeshpro", "AddPkg");
                Assert.IsNotNull(textAsset_Sync);
                Log("TextMeshPro", "Sync", "AddPkg", "demo_textmeshpro");

                TMP_FontAsset textAsset_Async = await YAService_Entity.Instance.LoadTMPFont_Async("demo_textmeshpro", "AddPkg");
                Assert.IsNotNull(textAsset_Async);
                Log("TextMeshPro", "Async", "AddPkg", "demo_textmeshpro");
            });
        }

        /// <summary>
        /// 加载 扩展包 所有文本(TextAsset)
        /// </summary>
        public void Test_Load_AddPkg_AllTextAssets()
        {
            UniTask.ToCoroutine(async () =>
            {
                List<TextAsset> textAssets_Sync = YAService_Entity.Instance.LoadAllOneAssets_Sync<TextAsset>("demo_textasset", "AddPkg");
                Assert.IsTrue(textAssets_Sync.Count > 0);
                Log("TextAsset", "Sync", "AddPkg", "demo_textasset");

                List<TextAsset> textAssets_Async = await YAService_Entity.Instance.LoadAllOneAssets_Async<TextAsset>("demo_textasset", "AddPkg");
                Assert.IsTrue(textAssets_Async.Count > 0);
                Log("TextAsset", "Async", "AddPkg", "demo_textasset");
            });
        }

        #endregion

    }
}